<- read.csv("C:/Users/Admin/OneDrive/Desktop/Office/MyStudyApp/merge.csv",header = TRUE) data
Creating Tables in R with Tern
Introduction
tern is an R package designed for streamlined clinical trial data analysis and reporting. Built on top of rtables, it provides ready-made statistical summaries and standardized formats to create accurate, regulatory-compliant tables with ease. Whether you’re summarizing safety or efficacy data, tern helps deliver clear, reproducible, and audit-ready clinical reports efficiently.
Import the data
About the data set
head(data)
Patient_ID Day VAS PGA Age Gender Treatment Center ITT PP
1 PID/001 DAY1 72 2 24 Female PLACEBO C1 YES YES
2 PID/001 DAY5 56 2 24 Female PLACEBO C1 YES YES
3 PID/001 DAY6 67 2 24 Female PLACEBO C1 YES YES
4 PID/001 DAY4 56 2 24 Female PLACEBO C1 YES YES
5 PID/001 DAY2 70 2 24 Female PLACEBO C1 YES YES
6 PID/001 DAY7 62 2 24 Female PLACEBO C1 YES YES
Create a summary table to analyse VAS for each Day grouped by treatment
# Load required packages
library(tern) # Provides clinical trial-specific statistical functions and reporting tools built on rtables
library(rtables) # Core package for building complex summary tables in R
library(dplyr) # Useful for data manipulation and preparation (optional but commonly used)
# Make sure 'Day' is a factor with the correct order
$Day <- factor(data$Day, levels = c("DAY1", "DAY2", "DAY3", "DAY4", "DAY5", "DAY6", "DAY7"))
data
# Define the layout of the summary table
<- basic_table() %>%
lyt # Split the columns of the table based on the 'Treatment' variable,
# so each treatment group appears as a separate column
split_cols_by("Treatment") %>%
# Split the rows of the table by 'Day', so each day is a separate row
split_rows_by("Day") %>%
# Specify the variables to analyze — here 'VAS' (Visual Analog Scale score)
# Define the statistics to compute:
# 'n' = number of non-missing observations
# 'mean_sd' = mean and standard deviation
# 'median' = median value
# 'min' = minimum value
# 'max' = maximum value
analyze_vars(
vars = "VAS",
.stats = c("n", "mean_sd", "median", "min", "max"),
# Format how each statistic is displayed in the table
# 'mean_sd' will be shown as "xx.xx (xx.xx)" i.e., mean (SD)
# median, min, and max will be shown as whole numbers ('xx')
.formats = c(
"mean_sd" = "xx.xx (xx.xx)",
"median" = "xx",
"min" = "xx",
"max" = "xx"
),
# Label the variable 'VAS' as "VAS Score" in the table header
var_labels = c(VAS = "VAS Score"),
# String to use for missing values (NA)
na_str = "NA"
)
# Build the table using the defined layout and the dataset
<- build_table(lyt, data)
tbl
# Print the resulting summary table to the console
tbl
PLACEBO TEST REF
———————————————————————————————————————————————————————————
DAY1
n 272 247 261
Mean (SD) 64.56 (14.56) 62.74 (17.61) 63.41 (16.75)
Median 66 72 72
Minimum 22 16 16
Maximum 91 87 87
DAY2
n 272 247 261
Mean (SD) 57.36 (14.18) 45.76 (20.66) 46.74 (19.88)
Median 58 48 48
Minimum 18 0 0
Maximum 86 80 81
DAY3
n 272 247 261
Mean (SD) 49.02 (16.32) 29.11 (21.70) 29.59 (21.48)
Median 51 30 29
Minimum 0 0 0
Maximum 77 75 77
DAY4
n 272 247 261
Mean (SD) 41.11 (15.08) 21.17 (17.79) 21.82 (17.68)
Median 45 23 24
Minimum 0 0 0
Maximum 68 65 66
DAY5
n 272 247 261
Mean (SD) 35.22 (15.21) 17.06 (15.82) 17.57 (15.76)
Median 36.5 17 19
Minimum 0 0 0
Maximum 60 64 65
DAY6
n 272 247 261
Mean (SD) 31.36 (17.27) 12.96 (14.36) 13.34 (14.63)
Median 29 4 4
Minimum 0 0 0
Maximum 68 65 64
DAY7
n 272 247 261
Mean (SD) 28.00 (18.21) 10.73 (13.71) 11.11 (13.99)
Median 26 3 3
Minimum 0 0 0
Maximum 69 62 62
Key Reasons to Use tern
Predefined Clinical Statistics : tern provides built-in summaries commonly required in clinical trials (e.g., n, mean, SD, median, min, max) without needing to manually write analysis functions, as you’d have to with rtables.
Standardized Formatting for Regulatory Tables : tern ensures your statistical outputs (like “mean (SD)”, “xx.x%”) follow CDISC/ICH-friendly formats — critical in clinical studies.
Less Manual Coding : In rtables, you’d need to write custom analysis functions, define custom format strings, handle NA cases manually while tern handles all of this with simple, ready-made calls like summarize_vars() or analyze_colvars().
Purpose-Built for Clinical Trial Workflows : tern is designed specifically to support TFL (Tables, Figures, Listings) generation — aligning with how real-world clinical reporting is done.
Why Choose tern Over gt, rtables, or flextable for Clinical Reporting?
The tern package is specifically designed for clinical trial reporting and regulatory submissions, offering built-in support for CDISC-compliant data and statistical summaries. Unlike gt and flextable, which focus on table styling for reports and presentations, and rtables, which provides a flexible framework for general-purpose tabulations, tern adds clinical-specific functionality on top of rtables. This makes it uniquely suited for generating tables with statistical rigor in regulated clinical research environments.
Conclusion:
The tern package empowers clinical researchers with a powerful, reliable tool to transform complex trial data into clear, standardized, and regulatory-ready reports. By combining ease of use with robust statistical methods and formatting, tern streamlines the clinical reporting workflow — helping teams deliver accurate insights faster and with confidence. It’s an essential asset for modern clinical data analysis in R.